/**
 * 
 */
package ar.edu.utn.frsf.cidisi.ginet.generation.choreography2ginet;

import java.util.HashMap;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.pnml.tools.epnk.pnmlcoremodel.Page;
import org.pnml.tools.epnk.pnmlcoremodel.PetriNet;

import ar.edu.utn.frsf.cidisi.ginet.GINet;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.AbstractGINet;
import ar.edu.utn.frsf.cidisi.ginet.formalization.FormalCBPLanguage;
import ar.edu.utn.frsf.cidisi.ginet.formalization.FormalElement;
import ar.edu.utn.frsf.cidisi.ginet.formalization.MetamodelElement;
import ar.edu.utn.frsf.cidisi.ginet.generation.abstract2concrete.AbstractGIM2ConcreteGIM;

/**
 * @author jmr
 *
 */
public class Choreography2GINet {
	
	private EObject rootElement;
	
	private EMap<MetamodelElement,FormalElement> formalElements;
	
	private AbstractGIM2ConcreteGIM agim2cgim;
	
	
	public Choreography2GINet(FormalCBPLanguage formalLanguage, EObject rootElement){
		this.rootElement = rootElement;
//		formalElements = formalLanguage.getFormalizedElements();
	}
	
	public void generateGINet(){
		
		
		
		HashMap<Page, EObject> pageObjectMap = new HashMap<Page, EObject>();

		// Get the abstract GI module for the root (first) element of the CBP model
		ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page agim = getAbstractModule(rootElement.eClass());
		AbstractGINet aGINet = (AbstractGINet)agim.eContainer();
		agim2cgim = new AbstractGIM2ConcreteGIM(aGINet);
		
		if (agim != null){
			
			Page rootPage = generateConcretePage(null, rootElement, agim);
	
			EList<EObject> objs = rootElement.eContents();

			addSubPages(rootPage, objs);
			

			

			generateGIModules(rootPage, objs);

		}



	}
	
	private void addSubPages(Page rootPage, EList<EObject>objs){

		for (EObject obj:objs){
			
			// Get the abstract GI module for the root (or first) element of the CBP model
			ar.edu.utn.frsf.cidisi.ginet.Page agim = getAbstractModule(rootElement.eClass());
			
			if (agim  != null){
				
				agim2cgim.createPage(rootPage, rootPage.getId()+agim.getId(), rootPage.getId()+agim.getId());

//				agim2cgim.createPage(obj.get, name)
//				pageObjectMap.put(key, obj);
				
			}
		}
	}
	

	private void generateGIModules(Page parentPage, EList<EObject> objs){
		
		for (EObject obj:objs){
			
			ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page agim = getAbstractModule(obj.eClass());
			
			if (agim != null){
				
				Page cgim = generateConcretePage(parentPage, obj, agim);
				
				if (cgim != null){
				
					// Generate GI modules for each nested element
					if (!obj.eContents().isEmpty())
						generateGIModules(cgim, obj.eContents());
					
				}
				
			}
			
		}
		
	}

	
	/**
	 * Returns the abstract GI module that formalizes the element of class elementClass.-
	 * 
	 * @param elementClass
	 * @return
	 *
	 * @author jmr
	 */
	private ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page getAbstractModule(EClass elementClass){
		
		Set<MetamodelElement> keys = formalElements.keySet();
		for (MetamodelElement key:keys){
			
			if (key.getElement().getName().equals(elementClass.getName()))
				return formalElements.get(key).getElement();
			
		}
		
		return null;
	
	}
	
	
	private Page generateConcretePage(Page parentPage, EObject element, ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page agim){
		
//		ACA HAY QUE BUSCAR LOS PLACES DE LA PARENTPAGE PARA SABER CUALES DE ELLOS DEBEN IR COMO REFERENCES EN LOS PLACES DE LAS SUBPAGINAS
//		parentPage.get
		int card = element.eContents().size();
		
		agim2cgim.setCardinality(agim, card);
		
		Page cgim = agim2cgim.addConcreteGIModule(agim);
		
		return cgim;
		
	}
	
	public void saveGINet(String path){
		agim2cgim.createPNMLFile(path);
	}
	
	public GINet getGINet(){
		return agim2cgim.getConcreteGINet();
	}
	
	

}
